
該文章同步發佈於:我的部落格
也歡迎關注我的 Facebook 以及 Instagram 接收軟體相關的資訊!
今天會開始介紹許多好用的 Matcher 也就是配對仔,從開始到現在我們都只使用過 eq 這種用法!
其實還有很多有趣的 Matcher 可以使用!
今天會介紹三種不同的 Matcher 但又很相似的,分別是 eq eql be !
eq 是我們最常使用的 Matcher,其概念也非常簡單,就是單純的比較 value,而不比較 type !
我們可以用一些示範來比喻一下!
RSpec.describe "eq matcher" do
let(:a) { 5.0 }
let(:b) { 5 }
it 'only tests for value' do
expect(a).to eq(5)
expect(b).to eq(5.0)
expect(a).to eq(b)
end
end
這會是一個全部通過的情況!我們也說過 eq 只看值,不看型別。
為什麼會這樣說呢?因為其實在 Ruby 的世界中 5 and 5.0 兩個人是屬於不同的類別!
若是在 IRB 中試試看:
> 5.class
> Integer
> 5.0.class
> Float
在 Ruby 的整數和浮點數是不同的類別,自然而然也不會是同一個 type!
但 eq 會略過型別的比對,專注在值是否吻合!
而一直強調型別,那會根據型別來判斷的 Matcher 是哪個呢?
雖然只差了一個 l 的字母,但在處理的嚴謹度上就完全不相同了!
如果一樣使用剛剛的範例,但改用 eql 來看看會發生什麼事情?
RSpec.describe "eql matcher" do
let(:a) { 5.0 }
let(:b) { 5 }
it 'tests for value and type' do
expect(a).to eql(5)
expect(b).to eql(5.0)
expect(a).to eql(b)
end
end
沒通過的結果:

他會告訴你,5 和 5.0 是不相同的東西,測試不通過!!!
你會想說,這樣有什麼差別啦,現實世界中 5 就是 5.0 啦~
但情境如果是在處理精密的匯率或是稅率等等,使用 eq 來做 Matcher 是不是會有一點草率呢?
使用 eql 能夠幫你在撰寫方法的時候考慮得更多!你也可以想像成嚴格模式啦~
因為它必須是 相同的 value 以及 相同的類別 才能被認定為相同!
接下來我想介紹更嚴格的一個 Matcher,他不只要你是同一個型別,他還要你是同一個物件!
會放在一起講的原因是 equal 等同於 be,所以接下來我們會一起示範這要怎麼用!
但在放上範例之前,我想提一個概念:
equality 意思是在確認兩個物件在基本的設計上一樣的!
identity 意思是在確認兩個物件是同一個物件!
為什麼會講這樣的概念呢?因為 equal 就是 identity 的概念,而上面的 eq eql 都像是 equality 的概念!
我們換個類比的方法,假設我在一條大街上,和我隔壁的鄰居蓋了一間一模一樣的房子 ( 是真的一模一樣,包含窗框、草皮、房門等等 )
你心裡會說,這兩個房子長得一模一樣欸!但你不會說這是同一個房子,對吧?
就算他們在怎麼像,像到完全看不出來差別,你還是能用地址來做判斷,他們還是兩間房子!
等等示範的 equal 就是在幫你檢查是不是同一個地址,同一個房子的概念!
而 eq eql 都只是看看照片說,這兩個根本一模一樣嘛~
廢話不多說,我們直接上 Code 吧!
RSpec.describe "equal matcher & be matcher" do
let(:a) { [7, 7, 7]}
let(:b) { [7, 7, 7]}
let(:c) { a }
it "test for object identity" do
expect(a).to eq(b)
expect(a).to eql(b)
expect(a).to equal(c)
expect(a).not_to equal(b)
end
end
上面是一個會全部通過的測試!
這邊的 c 變數,指向 a 變數,這代表著什麼?
我把我家的地址填得和你家地址一樣,我們兩個是一模一樣在同一個地方的物件!
而 a 和 b 在值以及型別上來看,都一模一樣,但他們在記憶體中的地址卻不相同,我們可以故意讓測試壞掉來看看 OutPut 是什麼?
我們讓 a equal b 來試試看!
錯誤的提示:

可以看到兩個在 Array 的記憶體位置是不相同的 ( 一個是 2800, 一個是 2820 ),這就像是房子的案例一樣,我們雖然一樣,但終究是兩個個體!
下面的提示也有告訴你,這是在比較物件的 identity!
剛剛範例上都使用
equal,但其實你也可以用be比較省力喔~
重新複習一下三者的不同之處!
eq:單純比較值,不在意型別
eql:比較值以及型別
equal 以及 be:比較值,型別,記憶體位置(是否為同一個物件)
希望以後大家在使用的時候,可以根據要測試的嚴謹程度來決定要使用哪一個 Matcher 喔!
這三個都是非常基礎的 Matcher 但卻常常不知道錯在哪,希望這篇文章可以幫助到你~